package com.Angaliwa{
	import com.Angaliwa.Whiteboard.*;
	
	import mx.containers.Canvas;
	import mx.core.UIComponent;
	
	public class Whiteboard{
		public var settings:Settings = new Settings(this);
		public var resizeHandler:ResizeHandler = Core.g('resizeHandler');
		
		/*
			Available daisyChain actions:
			- init
			- colorSet
			- thicknessSet
			- layerAdded
			- featureEnabled
			
			And every feature that is added receives it's own
			daisyChain actions, named:
			- feature[Name]Enabled
			- feature[Name]Disabled
			
			Where [Name] is the name of the feature.
		*/
		public var daisyChain:DaisyChain = new DaisyChain(this),
				   board:Canvas,
				   innerBoard:Canvas,
				   enabledFeature:String,
				   container:*,
				   features:Object = [];
		
		private var layers:Array = new Array();
		
		public function init(container:*, customSettings:Object=undefined):Whiteboard{
			this.container = container;
			
			// Initialize the default settings
			settings.setDefaults({ width: '100%',
								   height: '100%',
								   defaultLayerName:'default',
								   netStreamFieldName:'whiteboards',
								   syncWithServer:false});
			
			// Load up the custom settings, if any.
			if(customSettings) settings.add(customSettings);
			
			// Initialize the Whiteboard. We'll use a Canvas for this,
			// as it offers all the functionality we need.
			board = new Canvas();
			board.verticalScrollPolicy="off";
			board.horizontalScrollPolicy="off";
			
			
			// Add the whiteboard to the display
			container.addChild(board);
			
			// For when a custom size is specified.
			if(settings.get('width') && settings.get('height')){
				board.width = settings.get('width');
				board.height = settings.get('height');
			}
			
			// For when making use of Angaliwa's resizeHandler module.
			if(resizeHandler)
				resizeHandler.setSize(board, settings.get('width'), 
											 settings.get('height'))
							 .setPosition(board, settings.get('horizontal'),
							 					 settings.get('vertical'));
			else if(settings.get('width') && settings.get('height')){
				board.width = settings.get('width');
				board.height = settings.get('height');
			}
			
			// Apply any custom styles defined by the user.
			Toolbox.applyStyles(board, settings.get('styles'));
			
			// Whether or not layer support is enabled, we need at least one
			// layer that will contain all whiteboard elements.
			addLayer();
			
			/*
				Since Adobe offers no proper way to include classes on
				request, we'll have to manually define them here. It sucks
				ass, I know, but until Adobe figures out a way to write a
				freaking decent language/framework, we'll be stuck with this.
			*/
			
			// If network support is enabled, let's initialize the module
			// that handles all that here.
			if(settings.get('syncWithServer'))
				addFeature('sync', new Sync());
			
			// Load all features
			addFeature('hand', new Hand(),true);
			addFeature('draw', new Draw());
			addFeature('freeform', new Freeform());
			addFeature('text', new Text());
			addFeature('navigator', new Navigator());
			//addFeature('spectator', new Spectator());
			
			return this;
		}
		
		public function addFeature(name:String, obj:*, enabled:Boolean=false, initByDefault:Boolean=true):Whiteboard{
			features[name] = obj;
			features[name].whiteboard = this;
			
			if(features[name].hasOwnProperty("settings"))
				features[name].settings.add(settings.get(name));
			
			if(initByDefault)
				features[name].init();
			
			if(enabled) enableFeature(name);
			
			return this;
		}
		
		public function g():Canvas{
			return board;
		}
		
		public function getContainer():Canvas{
			if(innerBoard) return innerBoard;
				else return board;
		}
		
		public function getLayer(name:String=undefined):UIComponent{
			if(!name) name = settings.get('defaultLayerName');
			
			return getContainer().getChildByName(name) as UIComponent;
		}
		
		public function addLayer(name:String=undefined, level:String=undefined):Whiteboard{
			var layer:UIComponent = new UIComponent();
			layer.name = (name) ? name : settings.get('defaultLayerName');
			
			layers.push(name);
			getContainer().addChild(layer);
			
			// For when making use of Angaliwa's resizeHandler module.
			if(resizeHandler)
				resizeHandler.setSize(layer, settings.get('width'), 
											 settings.get('height'));
			else if(settings.get('width') && settings.get('height')){
				layer.width = settings.get('width');
				layer.height = settings.get('height');
			}
			
			return this;
		}
		
		public function enableFeature(name:String):void{
			// If a previous feature was enabled, disable it.
			if(enabledFeature){
				features[enabledFeature].enabled=false;
				daisyChain.run('feature'+enabledFeature+'Disabled');
			}
			
			// Enable the new feature.
			features[name].enabled=true;
			enabledFeature = name;
			
			daisyChain.run('featureEnabled', name);
			daisyChain.run('feature'+name+'Enabled');
		}
		
		public function setColor(color:String):Whiteboard{
			var clr:String = (color.substr(0,1) == "#") ? color.substring(1) : color;
			
			for(var c:String in features)
				if(features[c].hasOwnProperty('color'))
					features[c].color="0x"+clr;
			
			daisyChain.run('colorSet', clr);
			
			return this;
		}
		
		public function setThickness(thickness:int):Whiteboard{
			for(var c:String in features)
				if(features[c].hasOwnProperty('thickness'))
					features[c].thickness=thickness;
			
			daisyChain.run('thicknessSet', thickness);
			
			return this;
		}
	}
}